package cn.cdeden.knowledge.service.impl;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.FilesDistributeTree;
import cn.cdeden.knowledge.domain.TeamFilesTree;
import cn.cdeden.knowledge.domain.dto.*;
import cn.cdeden.knowledge.domain.enums.MessageTypeEnums;
import cn.cdeden.knowledge.domain.vo.PersonalFilesTreeVo;
import cn.cdeden.knowledge.enums.FileEnums;
import cn.cdeden.knowledge.enums.MessageFileTypeEnums;
import cn.cdeden.knowledge.enums.TeamParamEnum;
import cn.cdeden.knowledge.service.*;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.system.api.model.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.undertow.util.BadRequestException;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cdeden.knowledge.domain.FilesDistribute;
import cn.cdeden.knowledge.mapper.FilesDistributeMapper;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = FilesDistributeService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FilesDistributeServiceImpl extends ServiceImpl<FilesDistributeMapper, FilesDistribute> implements FilesDistributeService{

    private final FilesDistributeMapper filesDistributeMapper;

    private final FilesDistributeSenderService filesDistributeSenderService;

    private final FilesDistributeTreeService filesDistributeTreeService;

    private final TeamFilesTreeService teamFilesTreeService;

    private final TeamRelevanceRoleService teamRelevanceRoleService;

    private final FilesAttentionService filesAttentionService;

    private final SysMessageService messageService;

    private final FileService fileService;


    @Override
    public TableDataInfo<FilesDistributeDto> queryDistribute(FilesDistributeQueryParam query, Pageable pageable) {
        IPage<FilesDistribute> queryPage = PageUtil.toMybatisPage(pageable);
        QueryWrapper<FilesDistribute> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.eq("distributor", LoginHelper.getUserId());
//        predicate.eq("distributor", FileUserUtils.getUser().getId());
        predicate.orderByDesc("distribute_time");
        IPage<FilesDistribute> page = filesDistributeMapper.selectPage(queryPage, predicate);
        TableDataInfo<FilesDistribute> build = TableDataInfo.build(page);
//        PageInfo<FilesDistributeDto> filesDistributeDtoPageInfo = ConvertUtil.convertPage(page, FilesDistributeDto.class);
//        List<FilesDistributeDto> content = filesDistributeDtoPageInfo.getContent();
//        filesDistributeDtoPageInfo.setContent(content);
        return MapstructUtils.convertTableDataInfo(build, FilesDistributeDto.class);
    }

    @Override
    public TableDataInfo<FilesDistributeDto> querySend(FilesDistributeQueryParam query, Pageable pageable) {
        List<FilesDistributeSenderDto> list = filesDistributeSenderService.getByUserId(LoginHelper.getUserId());
        IPage<FilesDistribute> queryPage = PageUtil.toMybatisPage(pageable);
        QueryWrapper<FilesDistribute> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.orderByDesc("distribute_time");
        if (list.size() == 0) {
            return new TableDataInfo<>();
        }
        List<Integer> collect = list.stream().filter(action -> {
            return !StringUtils.equals(String.valueOf(action.getReceive()), "1");
        }).map(FilesDistributeSenderDto::getDistributeId).collect(Collectors.toList());
        if (collect.size() != 0) {
            predicate.in("id", collect);
        } else {
//            return new PageInfo<>();
            return new TableDataInfo<>();
        }
        IPage<FilesDistribute> page = filesDistributeMapper.selectPage(queryPage, predicate);
        TableDataInfo<FilesDistribute> build = TableDataInfo.build(page);
        return MapstructUtils.convertTableDataInfo(build, FilesDistributeDto.class);
    }

    @Override
    public boolean receiveFile(RecoverFileChooseAPath recoverFileChooseAPath) throws BadRequestException {
        String id = recoverFileChooseAPath.getId();
        LoginUser user = LoginHelper.getLoginUser();

        FilesDistribute filesDistribute = filesDistributeMapper.selectById(id);
        if (filesDistribute == null) {
            throw new BadRequestException("分发的文档已被分发人撤回");
        }
        filesDistributeTreeService.copyToPersonalLibByTreeVo(id, recoverFileChooseAPath.getParentId());
        filesDistributeSenderService.updateReceive(user.getUserId(), Integer.valueOf(id));

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(FilesDistributeDto resources) throws BadRequestException {
        resources.setDistributeTime(new Date());
        LoginUser user = LoginHelper.getLoginUser();
        resources.setDistributor(user.getUserId());
        resources.setDistributorName(user.getNickname());
        FilesDistribute entity = MapstructUtils.convert(resources, FilesDistribute.class);
        List<Long> userIds = resources.getUserIds();
        String treeNodeId = resources.getTreeNodeId();
        entity.setId(null);
        String[] split = treeNodeId.split(",");
        int insert = 0;
        if (resources.getType().equals("0")) {
            entity.setModules(FileEnums.PERSONAL_FILE.getCode());
            insert = filesDistributeMapper.insert(entity);
            for (String s : split) {
                PersonalFilesTreeVo personalFilesTreeVo = fileService.selectPersonalTree(s);
                personalFilesTreeVo.setParentId(null);
                FilesDistributeTree filesDistributeTree = filesDistributeTreeService.insertByPersonalFilesTreeVo(personalFilesTreeVo, entity.getId());

                //TODO 创建消息(待补充)
                //创建消息
                // ************************************************
//                MessageTypeChildEnums messageTypeChildEnums = null;
//                switch (personalFilesTreeVo.getType()) {
//                    case "file":
//                        messageTypeChildEnums = MessageTypeChildEnums.PERSONAL_DISTRIBUTE_FILE;
//                        break;
//                    case "folder":
//                        messageTypeChildEnums = MessageTypeChildEnums.PERSONAL_DISTRIBUTE_FOLDER;
//                        break;
//                    case "richText":
//                        messageTypeChildEnums = MessageTypeChildEnums.PERSONAL_DISTRIBUTE_RICHTEXT;
//                        break;
//                }
//
//                for (Long userId : userIds) {
//                    messageUtils.create(messageTypeChildEnums, String.valueOf(entity.getId()), String.valueOf(user.getId()),
//                        String.valueOf(userId), "您有需要接收的文档： “" + filesDistributeTree.getRealName() + "“。 分发人：" + user.getNickName());
//
//                }
//***********************************************************************************************
            }
        } else if (resources.getType().equals("1")) {
            entity.setModules(FileEnums.TEAM_FILE.getCode());
            insert = filesDistributeMapper.insert(entity);
            //TODO 团队相关的内容待补充
            //***********************************************************************************
            for (String s : split) {
                //获取团队文档及下级目录
//                TeamFilesTree teamFilesTreeHead = teamFilesTreeService.getById(s);
                TeamFilesTreeDto teamFilesTreeDto = teamFilesTreeService.selectTeamTree(s);
                teamFilesTreeDto.setParentId(null);

                TeamFilesTreeDto teamFilesTrees = filterPermission(teamFilesTreeDto, null);
                FilesDistributeTree filesDistributeTree = filesDistributeTreeService.insertByTeamFilesTree(teamFilesTrees, entity.getId());

                //添加消息
                List<String> attentionPeople = filesAttentionService.getAttentionPeople(String.valueOf(filesDistributeTree.getId()), "1");

                for (String attentionPerson : attentionPeople) {
                    //创建消息
                    SysMessageDto sysMessageDto = new SysMessageDto();
                    sysMessageDto.setContent("您有需要接收的文档： “" + filesDistributeTree.getRealName() + "“。 分发人：" + user.getNickname());
                    sysMessageDto.setOperator(user.getUserId().toString());
                    sysMessageDto.setNodeId(filesDistributeTree.getId().toString());
                    sysMessageDto.setMessageType("0");
                    sysMessageDto.setType(MessageTypeEnums.UPDATE.getCode());
                    sysMessageDto.setFileType(MessageFileTypeEnums.TEAM.getCode());
                    sysMessageDto.setRecipient(attentionPerson);
                    sysMessageDto.setTeamId(String.valueOf(teamFilesTrees.getTeamId()));
                    messageService.addMessage(sysMessageDto);
                }
            }
            //******************************************************************************************************************
        }

        for (Long userId : userIds) {
            FilesDistributeSenderDto filesDistributeSenderDto = new FilesDistributeSenderDto();
            filesDistributeSenderDto.setDistributeId(entity.getId());
            filesDistributeSenderDto.setSenderId(userId);
            filesDistributeSenderDto.setReceive(0);
            filesDistributeSenderService.insert(filesDistributeSenderDto);
        }

        return insert;
    }

    //剔除无分发权限的文档
    private TeamFilesTreeDto filterPermission(TeamFilesTreeDto teamFilesTreeDto, TeamFilesTreeDto parentTeamTreeDto) {
        Boolean aBoolean = teamRelevanceRoleService.checkPermission(String.valueOf(teamFilesTreeDto.getId()), teamFilesTreeDto.getTeamId(), LoginHelper.getLoginUser(), TeamParamEnum.DISTRIBUTE.getParam());
        //如果parentTeamTreeDto为null 这就是第一层
        if (parentTeamTreeDto == null && !aBoolean) {
            //第一层文档就没有分发的权限 抛出异常
            throw new RuntimeException("无该文档的分发权限");
        }
        if(!aBoolean){
            return null;
        }

        List<TeamFilesTreeDto> newChildren = new ArrayList<>();
        //继续剔除子级无权限文档
        for (TeamFilesTreeDto child : teamFilesTreeDto.getChildren()) {
            TeamFilesTreeDto childDto = filterPermission(child, teamFilesTreeDto);
            if (childDto != null){
                newChildren.add(childDto);
            }
        }
        teamFilesTreeDto.setChildren(newChildren);
        return teamFilesTreeDto;
    }
}
